#!/usr/bin/env python
#
#       Outgoing.py
#       
#       Copyright 2009 Ben Davis <its.hip@gmail.com>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

import Effects
import Game
import Interfaces
import Options
import Socket
import ToServer

from Client import Client
client = Client()

class Packet:
    """Base-class for packets. Simply put in the info you need to send
    and create a matching class in the Server Outgoing.py which acts upon
    the data on a __call__"""
    def __call__(self):
        pass

class AddPlayer(Packet):
    """Add a player to the game"""
    def __call__(self):
        client.game.players[self.player.key()] = self.player
        Interfaces.TimedBox(client, self.player.name + " entered the game.")

class AddShip(Packet):
    """Add a ship to player"""
    def __call__(self):
        client.game.players[self.player].ships[self.ship.key()] = self.ship

class Fire(Packet):
    def __call__(self):
        # For now, just damage ships instantly
        # Loop through all the ships damaged
        for ship, player, damage in self.damaged:
            target = client.game.players[player].ships[ship]
            # bop the target about a bit.
            target.xy_mod.push(client.game.players[self.player].ships[self.ship].weapons[self.weapon].recoil, target.get_direction_to_tile_2(client.game.players[self.player].ships[self.ship].x, client.game.players[self.player].ships[self.ship].y) + 4)
            # Take away the damage from health
            target.health -= damage
            # If ship has no health left
            if target.health <= 0:
                # Destroy it
                client.sounds.sfx('crit.ogg')
                target.die()
                del(client.game.players[player].ships[ship])
                # If this is client's selected ship
                if client.game.selected == target:
                    # Select nothing
                    client.game.selected = None
            else:
                target.hit(damage)
                client.sounds.sfx('hit.ogg')
        ship = client.game.players[self.player].ships[self.ship]
        ship.steam -= ship.weapons[self.weapon].steam
        ship.fire(self.weapon)

class GoLobby(Packet):
    """Give the player the server lobby."""
    def __call__(self):
        client.show_menu()
        client.menu.joinserver()
        client.sounds.music('March.ogg', -1, True)
        client.server.send(ToServer.Name())

class Message(Packet):
    def __call__(self):
        if client.chat or client.chat == []:
            Interfaces.Row(client.chat, ("[SYSTEM]:", self.message), True, (200,255,200))
            #print client.chat
        else:
            Interfaces.TimedBox(client, self.message)

class NewTurn(Packet):
    def __call__(self):
        client.game.players.turn = self.player
        client.sounds.sfx('nextturn.ogg')
        for ship in client.game.players[client.game.players.turn].ships.values():
            ship.steam += ship.steam_prod
            if ship.steam > ship.steam_max:
                ship.steam = ship.steam_max
        # If it's this player's turn
        if client.game.player.key() == client.game.players.turn:
            ship = client.game.player.ships.first_ship_with_steam()
            # If player has a ship with steam
            if ship:
                client.game.select((ship.x, ship.y))
        client.turnbox.redraw()

class Orders(Packet):
    def __call__(self):
        # Find the ship which has orders
        ship = client.game.players[self.player].ships[self.ship]
        # Point the orders to the ship
        for order in self.orders:
            order.ship = ship
        # Point the ship to the orders
        ship.orders = self.orders
        
class RemovePlayer(Packet):
    """Remove a player from the game"""
    def __call__(self):
        Interfaces.TimedBox(client, client.game.players[self.player].name + " left the game.")
        if client.game.selected in client.game.players[self.player].ships.values():
            client.game.selected = None
        del(client.game.players[self.player])
    
class Said(Packet):
    """Create a text box with whatever a player has said"""
    def __call__(self):
        if client.chat or client.chat == []:
            if self.playernumber == 1:
                colour = (200,255,255)
            elif self.playernumber == 2:
                colour = (255,200,200)
            else:
                colour = (255,255,255)
            Interfaces.Row(client.chat, (self.playername + ":", self.text), True, colour)
            #print client.chat
        else:
            Interfaces.TimedBox(client, client.game.players[self.player].name + ": " + self.text)

class Sync(Packet):
    """Send all players and the map"""
    def __call__(self):
        client.game = Game.Game(client)
        client.insert(0, client.game)
        client.game.players = self.players
        client.game.player = client.game.players[self.player]
        client.game.players.__setup__()
        client.game.map = self.map
        client.game.map.__setup__()
        # If it's this player's turn
        if client.game.player.key() == client.game.players.turn:
            ship = client.game.player.ships.first_ship_with_steam()
            # If player has a ship with steam
            if ship:
                client.game.select((ship.x, ship.y))
                if Options.PAN_ON_SELECT:
                    client.game.pan_to_ship(client.game.selected, 0)
        client.turnbox.redraw()
        client.server.send(ToServer.Name())

        
class Connect(Packet):
    """Go somewhere else?"""
    def __call__(self):
        # Close the connection with the old server nicely
        client.server.close()
        client.server = Socket.Server((self.server, self.port))
        client.server.start()
        client.server.send(ToServer.Name())

class Login(Packet):
    """OH HI I PLAY UR GAEMS"""
    def __call__(self):
        Interfaces.TimedBox(client.database.userloginreturns(self.username, self.password))
class Logout(Packet):
    """KTHXBAI"""
    def __call__(self):
        Interfaces.TimedBox(client.database.userlogoutreturns())
        
class Register(Packet):
    """Play with me =C"""
    def __call__(self):
        Interfaces.TimedBox(client.database.gameregister())
class Unregister(Packet):
    """FINE DON'T"""
    def __call__(self):
        Interfaces.TimedBox(client.database.gameunregister())
        
class Kill(Packet):
    """Kills the currently running game."""
    def __call__(self):
        client.game.close()
        
class Kick(Packet):
    """Kicks a certain client."""
    def __call__(self):
        client.kicked(self.reason)
        
class Smite(Packet):
    """Smites a ship for 100 damage."""
    def __call__(self):
        try:
            target = client.game.players[self.playerkey].ships[self.shipkey]
            #add lightning POW here
            target.health -= 100
            if target.health <= 0:
                # Destroy it
                client.sounds.sfx('crit.ogg')
                target.die()
                del(client.game.players[self.playerkey].ships[self.shipkey])
                # If this is client's selected ship
                if client.game.selected == target:
                    # Select nothing
                    client.game.selected = None
            else:
                target.hit(damage)
                client.sounds.sfx('hit.ogg')
        except KeyError:
            print "*fizzle*"
            print "that ship is gone, apparently."
            
class Win(Packet):
    """You just won!"""
    def __call__(self):
        print "Congratulations, you won!"
        Interfaces.WinLose(client, "win")

class Lose(Packet):
    """You just didn't win!"""
    def __call__(self):
        print "Commiserations, you lost!"
        Interfaces.WinLose(client, "lose")
        
class GameStart(Packet):
    """LET THE GAMES BEGIN!"""
    def __call__(self):
        print "The game is starting!"
        client.sounds.music('Battle1.ogg', -1, True)
        
class ClientListUpdate(Packet):
    """Here have some players"""
    def __call__(self):
        client.game.clientarray = self.clientarray
        try:    
            try:
                client.menu[2][1][2].refresh()
            except AttributeError:
                pass
        except IndexError:
            pass
